package com.example.shiro_springboot.matcher;

import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Element;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.springframework.stereotype.Component;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * 重写匹配器
 * 为了实现登录锁定
 */
@Component
public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher {

    // 缓存对象
    private Ehcache passwordRetryEhcache;

    public RetryLimitHashedCredentialsMatcher(EhCacheManager ehCacheManager) {
        passwordRetryEhcache = ehCacheManager.getCacheManager().getCache("passwordRetryEhcache");
    }

    // shiro的login方法自动调用
    // login -> realm 返回AuthenticationInfo   -> matcher
    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        // 缓存次数
        int i = 0;
        // 获取缓存中的错误次数
        String uname = token.getPrincipal().toString();
        Element element = passwordRetryEhcache.get(uname);
        if (element == null) {// 没有缓存错误的登录次数
            Element ele = new Element(uname, new AtomicInteger(0));
            passwordRetryEhcache.put(ele);
        } else {
            AtomicInteger value = (AtomicInteger) element.getObjectValue();
            i = value.incrementAndGet();
        }
        // 判断次数是否满足
        if (i >= 4) {
            throw new ExcessiveAttemptsException();
        }
        // 若不是4次，则进行登录认证，缓存的错误次数清空
        boolean match = super.doCredentialsMatch(token, info);
        if (match) {
            passwordRetryEhcache.remove(uname);
        }
        return match;
    }
}
